package com.hc.config;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @author hs
 * @date 2021/05/05
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * 作用是认证 就是声明哪些角色可以访问哪些页面
     * @param http 。
     * @throws Exception 。
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //请求授权的规则
        //首先是认证的请求 第二个是添加哪些地址 第三个是哪些可以访问第二个方法写的地址 permitAll()表示所有人都可以
        http.authorizeRequests()
                .antMatchers("/","/index.html").permitAll()
                .antMatchers("/level1/**").hasRole("vip1")
                .antMatchers("/level2/**").hasRole("vip2")
                .antMatchers("/level3/**").hasRole("vip3");
                //这里表示只有vip3这个角色可以访问这个目录下的页面

        //如果没有权限，设置为跳往登录页面 源码注解如下，解释了为什么一个方法就能跳往登录页
        //The most basic configuration defaults to automatically generating a login page at the URL "/login", redirecting to "/login?error" for authentication failure.
        //其实就是没有认证就走"/login" 如果认证错误就重定向"/login?error"  这两个页面是别人的，不是我们自己写的页面
        // 但是我们不想用它的登录页 想用我们自己的，就需要在后面加一个loginPage()
        http.formLogin()
                .loginPage("/toLogin")
                .usernameParameter("username")
                .passwordParameter("password")
                .loginProcessingUrl("/login");

        //开启注销的功能 注销成功返回首页
        http.logout().logoutSuccessUrl("/index");

        //关闭跨域请求伪造
        http.csrf().disable();

        //记住账号密码的实现 在原来的http.rememberMe() 加一个方法，方法参数就是表单项的name
        http.rememberMe().rememberMeParameter("remember");
    }


    /**
     * 作用是授权 就是表示用数据库或者是内存中查出来的数据 哪些人拥有vip1角色的权限  哪些人有拥有vip2角色的权限
     * @param auth 。
     * @throws Exception 。
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //查看源码注释的格式
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("admin").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2","vip3")
                .and()
                .withUser("hs").password(new BCryptPasswordEncoder().encode("123")).roles("vip1","vip2")
                .and()
                .withUser("guest").password(new BCryptPasswordEncoder().encode("123")).roles("vip1");
        //上面的是使用内存中的数据来进行模拟的
        //表示这个用户名和密码拥有什么角色的权限
    }
}
